<?php
// fBaseDeDatos.php
include_once "class.Busqueda.php";
include_once "class.BusquedaSimple.php";
include_once "class.BusquedaConCondicion.php";
include_once "class.BusquedaCompleta.php";

class fBaseDeDatos {	
	private static $f_instance; 
	//Constructor de la clase 
	function __construct(){
	}		
	
	/*	Parametros de salida: Objeto del tipo fBaseDeDatos
		Descripcion	: Patrón singleton, solo crea un nuevo objeto fBaseDedDatos si ya no existe una instancia del mismo.					
	*/	
	public static function getInstance(){ 
		if (!(self::$f_instance instanceof self)){ 
			self::$f_instance=new self(); 
		} 
		return self::$f_instance; 
	}
	
	/*	Parametros de entrada: $id-> Variable del tipo string que representa el usuario
							   $pass-> Variable del tipo string que representa la contraseña
		Parametros de salida:  $conexion-> Si la conexion es exitosa
							   FALSE-> Si hay un error durante la conexion	
	*/
	public function connect($id,$pass){
		$info = array("Database"=>"dts", "UID"=>"", "PWD"=>"");
		$conexion= sqlsrv_connect("",$info);
		if( $conexion ) {
			//echo "Connection established.<br />";
		}else{
			echo print_r( sqlsrv_errors(), true);
		}
		//if($conexion!=FALSE){
		//mssql_select_db("dts",$conexion);}
		return($conexion);
	}
	
	//	Parametros de entrada: $conexion-> Variable que representa una conexion a la base de datos, y se desea cerrar
	public function disconnect($conexion){
		sqlsrv_close($conexion);
	}
	
	/*	Parametros de entrada: $id-> variable del tipo string que representa el usuario
							   $password-> variable del tipo string que representa la contraseña
		Parametros de salida:  0-> Si la creacion del usuario fue exitosa
							   1-> Si no se realizo la creacion del usuario
		Descripcion	: Metodo que permite crear un usuario en la base de datos.					
	*/
	public function createUser($id,$password) {
		$conexion= $this->connect("","");
		$sql = "CREATE USER '$id'@'localhost' IDENTIFIED BY '$password';";
		$consulta= sqlsrv_query($conexion, $sql);
		if(!($consulta==FALSE)) {
			$sql = "GRANT SELECT,INSERT,UPDATE,DELETE ON tds.* TO '$id'@'localhost' IDENTIFIED BY '$password';";
			$consulta= sqlsrv_query($conexion, $sql);
				if(!($consulta==FALSE)) {
						$this->disconnect($conexion);
						return(0);
				}else {
					$this->disconnect($conexion);
					return(1);
				}				 
		} else {
			$this->disconnect($conexion);
			return(1);
		}
	}
	
	/*	Parametros de entrada: $obj-> Variable del tipo obj
		Parametros de salida:  0-> Si la insercion del obj fue exitosa
							   1-> Si no se realizo la insercion del obj
		Descripcion	: Metodo que permite insertar los valores de los atributos de 
					  obj en la tabla de obj en la base de datos
		Importante: Para el correcto funcionamiento del metodo la clase del 
					objeto a pasar como parametro de entrada deben tener 
					implementado el metodo get(atributo) y el metodo 
					getAtributos()
	*/
	public function insert($obj) {
		$nombreTabla= get_class($obj);
		$conexion= $this->connect("","");
		$string= "insert into $nombreTabla (";
		$string2= "values ('";
		$atributos = $obj->getAtributos();
        $N= sizeof($atributos);
        $i = 0;
        while ($obj->get($atributos[$i]) == null && $i < $N)
            $i++;
        if ($i >= $N) return 0;
        $string= $string.$atributos[$i];
        $string2= $string2.$obj->get($atributos[$i])."'";
        $i++;
		for (; $i < $N; $i++) {
			$atributo= $atributos[$i];
            $o = $obj->get($atributo);
            if ($o != null) {
                $string= $string.",".$atributo;
                $string2= $string2.", '".$o."'";
            }
		}
        $string2 = $string2.")";
        $string = $string.")";
		$string= $string.$string2;//echo '<script>alert("'.$string.'");</script>';
        //mssql_query("SET NAMES 'utf8'");
		$consulta= sqlsrv_query($conexion, $string) or die(print_r( sqlsrv_errors(SQLSRV_ERR_ALL), true));
		//echo '<script>alert("'.$consulta.'");</script>';
		if(!($consulta==FALSE)) {
			$this->disconnect($conexion);
			return(0);
		} else {
			print_r( sqlsrv_errors(SQLSRV_ERR_ALL), true);
			$this->disconnect($conexion);
			return(1);
		}
	}
		
	/*	Parametros de entrada: $obj-> Variable del tipo obj que es de una subclase
		Parametros de salida:  0-> Si la insercion del obj fue exitosa
							   1-> Si no se realizo la insercion del obj
		Descripcion	: Metodo que permite insertar los valores de los atributos de 
					  obj en la tabla de obj en la base de datos y en la tabla de la
					  clase padre de obj
	*/
	public function insertSubclass($obj) {
		$nombreTabla= get_class($obj);
		$conexion= $this->connect("","");
		$string= "insert into $nombreTabla (";
		$string2= "values ('";
		$atributos = $obj->getAtributos();
		$N= sizeof($atributos);
		for ($i = 0; $i < $N; $i++) {
			$atributo= $atributos[$i];
			if ($i != $N-1) {
				$string= $string.$atributo.",";
				$string2= $string2.$obj->get($atributo)."','";
			}else{
				$string= $string.$atributo.") ";
				$string2= $string2.$obj->get($atributo)."')";
			}	
		}
		$string= $string.$string2;
		$consulta= sqlsrv_query($conexion, $string);
		if(!($consulta==FALSE)) {
			$nombreTabla= get_parent_class($obj);
			$string= "insert into $nombreTabla (";
			$string2= "values ('";
			$atributos = $obj->getAtributosP();
			$N= sizeof($atributos);
			for ($i = 0; $i < $N; $i++) {
			$atributo= $atributos[$i];
				if ($i != $N-1) {
				$string= $string.$atributo.",";
				$string2= $string2.$obj->get($atributo)."','";
				}
				else {
				$string= $string.$atributo.") ";
				$string2= $string2.$obj->get($atributo)."')";
				}	
			}
			$string= $string.$string2;
			$consulta= sqlsrv_query($conexion, $string);
			if(!($consulta==FALSE)) {
			  $this->disconnect($conexion);
			  return(0);
			} else {
			  die( print_r( sqlsrv_errors(), true));
			  $this->disconnect($conexion);
			  return(1);
			}
		} else {
			$this->disconnect($conexion);
			return(1);
		}
	}
		
	/*	Parametros de entrada: $Busqueda: variable de tipo Busqueda que contiene el string para consultar la base de datos	
		Parametros de salida:    $result: Tupla(s) resultado de la busqueda 
		Descripcion	: Metodo que permite realizar una busqueda en la base de datos
	*/
	public function search ($Busqueda) {
		$conexion= $this->connect("","");
		$string= $Busqueda->consulta();// $string contiene el string de la consulta
		$result = sqlsrv_query($conexion, $string);
		$salida = array();
		$salida[0]= $result;
		$salida[1]= $conexion;
		return $salida;
	}
	public function search1($Busqueda) {
		$conexion= $this->connect("","");
		$string= $Busqueda->consulta1();// $string contiene el string de la consulta
		$result = sqlsrv_query($conexion, $string);
		$salida = array();
		$salida[0]= $result;
		$salida[1]= $conexion;
		return $salida;
	}
	/*	Parametros de entrada: $obj-> Variable del tipo obj que es de una subclase
							   $parametro-> Nombre del parametro clave para modificar el objeto.
							   $v_viejo -> Valor de la clave del objeto antes de realizar la modificacion.
		Parametros de salida: 0-> Si la actualizacion del obj fue exitosa
							  1-> Si no se realizo la actualizacion del obj
		Descripcion	: Metodo que permite actualizar los valores de los atributos de 
					  obj en la tabla de obj en la base de datos y en la tabla de la
					  clase padre de obj
	*/
	public function updateSubclass($obj,$parametro,$v_viejo) {
		$nombreTabla= get_class($obj);
		$conexion= $this->connect("","");
		$string= "update $nombreTabla set ";
		$atributos = $obj->getAtributos();
		$N= sizeof($atributos);
		for ($i = 0; $i < $N; $i++) {
			$atributo= $atributos[$i];
			if ($i != $N-1) {
				$string= $string.$atributo."='".$obj->get($atributo)."', ";
			}
			else {
				$string= $string.$atributo."='".$obj->get($atributo)."' ";
			}	
		}
		$string= $string."where $parametro='".$v_viejo."';";
		$consulta= sqlsrv_query($conexion, $string);
		if(!($consulta==FALSE)) {
			$nombreTabla= get_parent_class($obj);
			$string= "update $nombreTabla set ";
			$atributos = $obj->getAtributosP();
			$N= sizeof($atributos);
			for ($i = 0; $i < $N; $i++) {
			$atributo= $atributos[$i];
				if ($i != $N-1) {
				$string= $string.$atributo."='".$obj->get($atributo)."', ";
				}
				else {
				$string= $string.$atributo."='".$obj->get($atributo)."' ";
				}	
			}
			$string= $string."where $parametro='".$v_viejo."'";
			$consulta= sqlsrv_query($conexion, $string);
			if(!($consulta==FALSE)) {
			  $this->disconnect($conexion);
			  return(0);
			} else {
			  $this->disconnect($conexion);
			  return(1);
			}
		} else {
			die( print_r( sqlsrv_errors(), true));
			$this->disconnect($conexion);
			return(1);
		}
	}
	
	/*	Parametros de entrada:	$obj-> Variable del tipo obj que es de una subclase
								$parametro-> Nombre del parametro clave para modificar el objeto.
								$v_viejo-> Valor de la clave del objeto antes de realizar la modificacion.
								$simbolo-> Variable del tipo string que representa el operador para comparar el parametro y v_viejo
		Parametros de salida: 	0-> Si la actualizacion del obj fue exitosa
								1-> Si no se realizo la actualizacion del obj
		Descripcion	: Metodo que permite actualizar los valores de los atributos de 
					  obj en la tabla de obj en la base de datos 
    */
    public function update($obj,$parametro,$v_viejo,$simbolo) {
		$nombreTabla= get_class($obj);
		$conexion= $this ->connect("","");
		$string= "update $nombreTabla set ";
		$atributos = $obj->getAtributos();
		$N= sizeof($atributos);
        $i = 0;
		while ($obj->get($atributos[$i]) == null && $i < $N)
            $i++;
        if ($i >= $N) return 0;
		$string= $string.$atributos[$i]."='".$obj->get($atributos[$i])."'";
		for (; $i < $N; $i++) {
			$atributo= $atributos[$i];
            $o = $obj->get($atributo);
            if ($o != null && $i>0)
                $string= $string.", ".$atributo."='".$o."'";
		}
		$string= $string."where $parametro"."$simbolo"."'$v_viejo'";
		$consulta= sqlsrv_query($conexion, $string);
		if(!($consulta==FALSE)) {
		    $this->disconnect($conexion);
			return(0);
		} else {
			die( print_r( sqlsrv_errors(), true));
			$this->disconnect($conexion);
			return(1);
		}		
	}
    	
	/*	Parametros de entrada: $obj-> Variable del tipo obj que es de una subclase
							   $parametro-> Nombre del parametro clave para modificar el objeto.
							   $simbolo-> Variable del tipo string que representa el operador para comparar el parametro 
										  y el valor del atributo a	eliminar
		Parametros de salida:  0-> Si se elimina el obj de forma exitosa de la tabla
							   1-> Si no se eliminar el obj de la tabla
		Descripcion	: Metodo que permite eliminar la tupla de obj de la tabla 
					  del tipo obj
    */
	public function delete ($obj,$parametro,$simbolo) {
		$nombreTabla= get_class($obj);
		$conexion= $this->connect("","");
		$aEliminar= $obj->get($parametro);
		$sql="delete from $nombreTabla where $parametro"."$simbolo"."'$aEliminar'";
		$consulta= sqlsrv_query($conexion, $sql);
		if(!($consulta==FALSE)) {
			$this->disconnect($conexion);
			return(0);
		} else {
			die( print_r( sqlsrv_errors(), true));
			$this->disconnect($conexion);
			return(1);
		}
	}
	
	/*	Parametros de entrada: $obj-> Variable del tipo obj que es de una subclase
							   $parametro-> Nombre del parametro clave para modificar el objeto.
							   $simbolo-> Variable del tipo string que representa el operador para comparar el parametro y 
										  el valor del atributo a eliminar
		Parametros de salida:  0-> Si se elimina el obj de forma exitosa de la tabla
							   1-> Si no se eliminar el obj de la tabla
		Descripcion	: Metodo que permite eliminar la tupla de obj de la tabla 
					  del tipo obj.
		Recomendacion: Usar este metodo cuando deseamos eliminar obj que sus claves son compuestas
    */
	public function deleteConVariosParametros ($obj,$simbolo) {
		$nombreTabla= get_class($obj);
		$conexion= $this->connect("","");
		$atributos = $obj->getAtributos();
		$N= sizeof($atributos);
		$string= "delete from $nombreTabla where ";
		for ($i=0; $i<$N; $i++) {
			$atributo= $atributos[$i];
			$valor= $obj->get($atributo);
			if ($i != $N-1) {	
				$string= $string."$atributo"."$simbolo"."'$valor' "."AND ";
			}
			else {
				$string= $string."$atributo"."$simbolo"."'$valor'";
			}
		}
		$consulta= sqlsrv_query($conexion, $string);
		if(!($consulta==FALSE)) {
			$this->disconnect($conexion);
			return(0);
		} else {
			die( print_r( sqlsrv_errors(), true));
			$this->disconnect($conexion);
			return(1);
		}
	}
	
	public function updateConVariosParametros ($obj,$obj_viejo,$simbolo) {
		$nombreTabla= get_class($obj);
		$conexion= $this ->connect("","");
		$string= "update $nombreTabla set ";
		$atributos = $obj->getAtributos();
		$N= sizeof($atributos);
		for ($i = 0; $i < $N; $i++) {
			$atributo= $atributos[$i];
			$valor = $obj->get($atributo);
			if ($i != $N-1) {
				if ($valor==null) $string= $string.$atributo."=NULL,";
				else $string= $string.$atributo."='".$valor."',";
			}
			else {
				if ($valor==null) $string= $string.$atributo."=NULL";
				else $string= $string.$atributo."='".$valor."' ";
			}	
		}
		$string= $string."where ";
		$atributos= $obj_viejo->getAtributos();
		$N= sizeof($atributos);
		for ($i=0; $i<$N; $i++) {
			$atributo= $atributos[$i];
			$valor= $obj_viejo->get($atributo);
			if (!($valor==NULL)){
			if ($i != $N-1) {	
				$string= $string."$atributo"."$simbolo"."'$valor' "."AND ";
			}
			else {
				$string= $string."$atributo"."$simbolo"."'$valor'";
			}}
		}
		$consulta= sqlsrv_query($conexion, $string);
		if(!($consulta==FALSE)) {
		    $this->disconnect($conexion);
			return(0);
		} else {
			echo print_r( sqlsrv_errors(), true);
			$this->disconnect($conexion);
			return(1);
		}
	}
	
	public function autocompletarObjeto($obj,$clavePrimaria) {
		foreach ($clavePrimaria as $parteClave) if ($obj->get($parteClave) == NULL)	return 1;
		$nombre = array ();
		$nombre[0] = get_class($obj);
		$columnas = array();
		$columnas[0]= "*";
		$valores= array();
		$i=0;
		foreach ($clavePrimaria as $parteClave){	
			$valores[$i]= $obj->get($parteClave);
			$i=$i+1;
		}
		$Busqueda= new BusquedaConCondicion($nombre,$columnas,$clavePrimaria,$valores,"=","AND");
		$ar = $this->search($Busqueda);
		$con = $ar[1];
		$c = $ar[0];
		if ($lista=sqlsrv_fetch_array($c)){
			$atributos=$obj->getAtributos();
			foreach ($atributos as $atributo)	$obj->set($atributo,$lista[$atributo]);
			//para clases que poseen id's postizos
			if($obj->poseeIdPostizo()){	$obj->set('id',$lista['id']);}
			$this->disconnect($con);
			return 0;
		}else{
			die( print_r( sqlsrv_errors(), true));
			$this->disconnect($con);
			return 1;
		}
	}
    
    public function contar($obj) {
		$nombreTabla= get_class($obj);
		$conexion= $this->connect("","");
		$sql="select COUNT(*) from $nombreTabla";
		$consulta= sqlsrv_query($conexion, $sql);
		if(!($consulta==FALSE)) {
			$this->disconnect($conexion);
			return $consulta[0];
		} else {
			die( print_r( sqlsrv_errors(), true));
			$this->disconnect($conexion);
			return 0;
		}
	}
}